﻿using HuaCheng.DataAccess;
using HuaCheng.Model;
using HuaCheng.SendAndReceive;
using HuaCheng.Views;
using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Windows.Forms;

namespace HuaCheng.Controller
{
    class TcpControl
    {
        //独立模式动作包
        public static CommandProtocol.IndependAction inAction = new CommandProtocol.IndependAction();
        //并联模式动作包
        public static CommandProtocol.ParalleAction paAction = new CommandProtocol.ParalleAction();
        public static byte[] temp = null;
        public static string[] lastCauses = new string[8];
        //关机校验的事件和委托
        public delegate void ErrorCloseJudge(string ip,int cid,int stepNum,int gid,CommandProtocol.IndependAction inAction,CommandProtocol.ParalleAction paAction,bool isParalle);
        public static event ErrorCloseJudge ChannelErrorCloseJudge;
        public delegate void ErrorShowJudge(string ip, int cid,int gid,bool isError);
        public static event ErrorShowJudge ChannelErrorShowJudge;
        //从数据库中查出的故障的字段名和中文名
        public static List<string> errCode = DicHelper.RetrieveError(true);
        public static List<string> errName = DicHelper.RetrieveError(false);
        public static void OnErrorCloseJudge(string ip,int cid,int stepNum,int mid,CommandProtocol.IndependAction inAction,CommandProtocol.ParalleAction paAction,bool isParalle)
        {
            if (ChannelErrorCloseJudge != null)
            {
                ChannelErrorCloseJudge(ip,cid,stepNum,mid,inAction,paAction,isParalle);
            }
        }
        public static void OnErrorShowJudge(string ip,int cid,int mid,bool isError)
        {
            if(ChannelErrorShowJudge!=null)
            {
                ChannelErrorShowJudge(ip, cid, mid,isError);
            }
        }
        #region 发送数据给客户端
        /// <summary>
        /// 异步发送指令
        /// </summary>
        /// <param name="state"></param>
        public static void Send(byte[] data,Socket client,string ip)
        {
            try
            {
                client.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);//无延迟发送
                client.BeginSend(data, 0, data.Length, SocketFlags.None,
                new AsyncCallback(SendDataEnd), client);
                //if (data.Length == 26)//如果为动作包
                //{
                //    Console.WriteLine("---------------send以后设备ip:" + ip + "通道号：" + data[9] + " 开机位的值:" + data[19]);
                //}        
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + ex.StackTrace);
            }
        }
        /// <summary>
        /// 向客户端发送数据的异步回调委托
        /// </summary>
        /// <param name="ar"></param>
        private static void SendDataEnd(IAsyncResult ar)
        {
           int send =((Socket)ar.AsyncState).EndSend(ar);
           //Console.WriteLine("发送的字节数:" + send);
        }
        #endregion
        /// <summary>
        /// 记录故障
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="client"></param>
        public static void RecordError(object state)
        {
            //AsyncSocketState asyState = (AsyncSocketState)state;
            StateBag stateBag = (StateBag)state;
            byte[] bytes = stateBag.bufferData;
            Socket client = stateBag.clientSocket;
            //string[] str = Convert.ToString(client.RemoteEndPoint).Split(new char[] { ':' });           
            //记录故障
            List<Errors> errs = new List<Errors>();
            string ip = stateBag.ip;
            for (int i = 0; i < 8; i++)
            {
                ChannelState cs = ChannelStateControl.byte2Channel(bytes, i, 76);               
                errs = CheckError(cs, i, ip, errCode,errName,errs,client);              
            }
            if (errs.Count > 0)//有故障时插入数据库历史故障表和每日故障表
            {
                ErrorHelper.ModifyHistoryErr(errs);//历史故障表
            }
        }
        /// <summary>
        /// 检查故障
        /// </summary>
        /// <param name="cs"></param>
        /// <param name="client"></param>
        /// <param name="i"></param>
        /// <param name="ip"></param>
        /// <param name="errDic"></param>
        /// <param name="errs"></param>
        /// <returns></returns>
        public static List<Errors> CheckError(ChannelState cs,int i,string ip,List<string> errCode,List<string> errName,List<Errors> errs,Socket client)
        {
            Type type = cs.GetType();
            string errCauses = "";
            Errors err = new Errors();
            int realId = 0;
            //有故障产生
            if (cs.ACstate2_AC_fault == true || cs.DCstate1_DC_fault == true)
            {
                //获取故障信息
                err.GID = cs.GID;
                err.CID = i;
                err.MID = cs.MID;
                err.IP = ip;
                DateTime dt = DateTime.Now;
                err.OccurTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");                   
                for(int j = 0;j < errCode.Count; j++)
                {
                    if((bool)type.GetProperty(errCode[j]).GetValue(cs) == true)
                    {
                        errCauses += errName[j] + ",";
                    }
                }
                realId = i;
                try
                {
                    if (IndexPage.allDevChl.ContainsKey(ip))
                    {
                        //如果通道没有处于已关机的状态,则进行关机
                        if (IndexPage.allDevChl[ip][realId].ChlStepName != "故障" && IndexPage.allDevChl[ip][realId].ChlStepName != "完成" && IndexPage.allDevChl[ip][realId].ChlStepName != "保护" && IndexPage.allDevChl[ip][realId].ChlStepName != "开机中")
                        {
                            //触发关机校验委托事件，传回正在关机的通道号
                            OnErrorCloseJudge(ip, i, 1, cs.MID, inAction, paAction, false);
                        }
                        else
                        {
                            if (IndexPage.allDevChl[ip][realId].ChlStepName == "故障")
                            {
                                //获取该通道最新的故障信息
                                Errors lastError = ErrorHelper.GetHistoryErrors(ip, cs.GID + 1, cs.MID + 1, i + 1);
                                string lastErrorCause = lastError.ErrorCause;
                                if (lastErrorCause != null)
                                {
                                    if (lastErrorCause.Equals(errCauses.Substring(0, errCauses.Length - 1)))
                                    {
                                        errCauses = "";
                                    }
                                }
                                //与内存中记录的故障信息比对，防止由于数据库插入缓慢导致系统误以为故障未记录的情况
                                if (lastCauses[i] != null)
                                {
                                    if (lastCauses[i].Equals(errCauses))
                                    {
                                        errCauses = "";
                                    }
                                }
                            }
                        }
                    }
                }
                catch(Exception e)
                {
                    Console.WriteLine(e.StackTrace + e.Message);
                }
                if (errCauses != "")//如果有故障则添加到故障列表
                {
                    lastCauses[i] = errCauses;
                    try
                    {
                        if (IndexPage.allDevChl.ContainsKey(ip))
                        {
                            if (IndexPage.allDevChl[ip][realId].ChlStepName != "故障")
                            {
                                //变更通道状态
                                OnErrorShowJudge(ip, i, cs.MID, true);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.StackTrace + e.Message);
                    }
                    err.ErrorCause = errCauses.Substring(0, errCauses.Length - 1);//去掉最后一个逗号
                    errs.Add(err);
                }
            }
            else
            {
                realId = i;
                try
                {
                    if (IndexPage.allDevChl.ContainsKey(ip))
                    {
                        if (IndexPage.allDevChl[ip][realId].ChlStepName == "故障")
                        {
                            OnErrorShowJudge(ip, i, cs.MID, false);
                        }
                    }            
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.StackTrace + e.Message);
                }
            }
            return errs;
        }
        /// <summary>
        /// 通道发生通信故障
        /// </summary>
        /// <param name="state"></param>
        public static void ConnectShowMsg(object state)
        {
            string ip = (string)state;
            MessageBox.Show("设备 " + ip + " 发生通信故障", "提示", MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
        }
    }
}
